#include <arm.h>
#include <trap.h>
#include <stdio.h>
#include <picirq.h>

/* *
 * Support for time-related hardware gadgets
 * */

/* Timer 0 and Timer 4 registers */
#define TCFG0		0x51000000
#define TCFG1		TCFG0 + 0x04
#define TCON		TCFG0 + 0x08
#define TCNTB0		TCFG0 + 0x0C
#define TCMPB0		TCFG0 + 0x10
#define TCNTB4		TCFG0 + 0x3C


/* Timer 0 and Timer 4 registers values */
#define TIMER4_PRE0		0 << 4
#define TIMER4_PRE256	0xFF << 8
#define TIMER4_DIV16	3 << 16
#define TIMER4_ENABLE	1 << 20
#define TIMER4_UPDATE	1 << 21
#define TIMER4_AUTO		1 << 22

#define TIMER0_PRE256	0xFF
#define TIMER0_DIV16	0x3
#define TIMER0_ENABLE	1
#define TIMER0_UPDATE	1 << 1
#define TIMER0_AUTO		1 << 3

volatile size_t ticks;

/* *
 * clock_init - initialize TIMER4 to interrupt 100 times per second,
 * and then enable INT_TIMER4 (IRQ).
 * PCLK = 50 Mhz, divider = 1/16, prescaler = 24, TCNT = 1267
 * */
void
clock_init(void) {
	// Set Prescaler and divider
	outw(TCFG0, inw(TCFG0) | 24 << 8); // Timer4
	//outw(TCFG0, inw(TCFG0) | 24); // Timer0
	outw(TCFG1, TIMER4_DIV16);

	// Auto reload
	outw(TCON, TIMER4_AUTO);

	// Set value, update, set value again
	// There is a bug actually. Value is always 1267 in skyeye whatever I write.
	outb(TCNTB4, (uint8_t) 1267);
	outw(TCON, inw(TCON) | TIMER4_UPDATE);
	outb(TCNTB4, (uint8_t) 1267);
	outw(TCON, inw(TCON) & ~(TIMER4_UPDATE));
	
    // initialize time counter 'ticks' to zero
    ticks = 0;
	
	// launch timer and enable timer interrupt INT_TIMER4
	outw(TCON, inw(TCON) | TIMER4_ENABLE);
	pic_enable(INT_TIMER4);
	
    cprintf("++ setup timer interrupts\n");
}

